#include "usbcore.h"
#include "pdiusbd12.h"
#include "uart.h"
#include "config.h"

#include <stdio.h>

// USB request section
uint8_t bmRequestType;
uint8_t bmRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
uint8_t* pSendData;
uint16_t SendLength;
uint8_t NeedZeroPacket;
uint8_t Ep1InIsBusy;
uint8_t ConfigValue;


code uint8_t DeviceDescriptor[0x12] = {
	0x12, // bLength, device descriptor length 18(0x12)
	0x01, // bDescriptorType,device descriptor num 0x01
	0x10,
	0x01, // bcdUSB
	0x00, // dDeviceClass
	0x00, // bDeviceClassSub
	0x00, // bDeviceProtocol
	0x10, // MaxPacketSize
	0x88,
	0x88, // idVender
	0x01,
	0x00, // idProduct
	0x00,
	0x01, // bcdDevice
	0x01, // Maunfacturer
	0x02, // iPdroduct
	0x03, // iSerialNumber
	0x01, // bNumConfiguration
};

idata uint8_t Buffer[16] = {0};

/**
 * config descriptor sets
 * 配置描述符的集合以及实现
*/

// USB报告描述符的定义
code uint8_t ReportDescriptor[] = {
	0x05, 0x01, 	// usage_page(generic desktop)
	0x09, 0x02, 	// usage(Mouse)
	0xa1, 0x01, 	// collection(application)
	0x09, 0x01, 	// usage(pointer)
	0xa1, 0x00, 	// collection(physical)

	0x05, 0x09, 	// usage_page(button)
	0x19, 0x01, 	// usage_minimum(button1)
	0x29, 0x03, 	// usage_maximum(button3)
	0x15, 0x00, 	// logic_minimum(0)
	0x25, 0x01, 	// logic_maximum(1)
	0x95, 0x03, 	// report_count(3)
	0x75, 0x01, 	// report_size(1)
	0x81, 0x02, 	// input(data,var,abs)
	0x95, 0x01, 	// report_count(1)
	0x75, 0x05, 	// report_size(5)
	0x81, 0x03, 	// input(cnts,var,abs)

	0x05, 0x01, 	// usage_page(generic desktop)
	0x09, 0x30, 	// usage(x)
	0x09, 0x31, 	// usage(y)
	0x09, 0x38, 	// usage(wheel)
	0x15, 0x81, 	// logic_minimum(-127)
	0x25, 0x7f, 	// logic_maximum(127)
	0x75, 0x08, 	// report_size(8)
	0x95, 0x03, 	// report_count(3)
	0x81, 0x06, 	// input(data,var,rel)
	0xc0, 	// end_collection
	0xc0, 	// end_collection
};

const uint8_t ConfigurationDescriptor[9+9+9+7] = {
	/* config descriptor */
	0x09, // bLength
	0x02, // descriptor type
	sizeof(ConfigurationDescriptor) & 0xFF,  // LOW byte
	(sizeof(ConfigurationDescriptor)>>8) & 0xFF, // High Byte total length
	0x01, // bNumInterface
	0x01, // configuration value
	0x00, // configuration
	0x80, // bmAttributes
	0x32, // bMaxPower
	/** interface descriptor */
	0x09, 	// bLength
	0x04, 	// bDescriptorType
	0x00, 	// bInterface Number
	0x00, 	// bAlternate Setting
	0x01, 	// bANumEndPoints
	0x03, 	// bInterfaceClass
	0x01, 	// bInterfaceSubClass
	0x02, 	// bInterfaceProtocol
	0x00, 	// bInterface

	/*** HID Descriptor */
	0x09, 	// bLength
	0x21, 	// bDescriptorType
	0x10, 	// bcdHID
	0x01, 	// bcdHID
	0x21, 	// bCountryCode
	0x01, 	// bNumDescriptor
	0x22, 	// bDescriptorType

	/*** HID report descriptor */
	sizeof(ReportDescriptor) & 0xFF, 	// wDescriptorLength
	(sizeof(ReportDescriptor)>>8) & 0xFF, 	// wDescriptorLength
	// bDescriptorType
	// bDescriptorLength

	/** Endpoint Descriptor */
	0x07, 	// bLength
	0x05, 	// bDescriptorType
	0x81, 	// bEndPointAddress
	0x03, 	// bmAttributes
	0x10, 	// wMaxPacketSize
	0x00, 	// wMaxPacketSize
	0x0A, 	// bInterval
};

/**
 * string descriptor
*/
/************************语言ID的定义********************/
code uint8_t LanguageId[4]=
{
	0x04, //本描述符的长度
	0x03, //字符串描述符
	//0x0409为美式英语的ID
	0x09,
	0x04
};
////////////////////////语言ID完毕//////////////////////////////////

/**************************************************/
/*********        本转换结果来自         **********/
/********* Http://computer00.21ic.org    **********/
/*********        作者: 电脑圈圈         **********/
/*********         欢迎大家使用          **********/
/*********    版权所有，盗版请写明出处   **********/
/**************************************************/
code uint8_t ManufacturerStringDescriptor[82]={
	82,         //该描述符的长度为82字节
	0x03,       //字符串描述符的类型编码为0x03
	0x35, 0x75, //电
	0x11, 0x81, //脑
	0x08, 0x57, //圈
	0x08, 0x57, //圈
	0x84, 0x76, //的
	0x55, 0x00, //U
	0x53, 0x00, //S
	0x42, 0x00, //B
	0x13, 0x4e, //专
	0x3a, 0x53, //区
	0x20, 0x00, //
	0x48, 0x00, //H
	0x74, 0x00, //t
	0x74, 0x00, //t
	0x70, 0x00, //p
	0x3a, 0x00, //:
	0x2f, 0x00, ///
	0x2f, 0x00, ///
	0x67, 0x00, //g
	0x72, 0x00, //r
	0x6f, 0x00, //o
	0x75, 0x00, //u
	0x70, 0x00, //p
	0x2e, 0x00, //.
	0x65, 0x00, //e
	0x64, 0x00, //d
	0x6e, 0x00, //n
	0x63, 0x00, //c
	0x68, 0x00, //h
	0x69, 0x00, //i
	0x6e, 0x00, //n
	0x61, 0x00, //a
	0x2e, 0x00, //.
	0x63, 0x00, //c
	0x6f, 0x00, //o
	0x6d, 0x00, //m
	0x2f, 0x00, ///
	0x39, 0x00, //9
	0x33, 0x00, //3
	0x2f, 0x00  ///
};
/////////////////////////厂商字符串结束/////////////////////////////

//字符串“《圈圈教你玩USB》之用户自定义的USB设备”的Unicode编码
//8位小端格式
code uint8_t ProductStringDescriptor[34]={
	34,         //该描述符的长度为34字节
	0x03,       //字符串描述符的类型编码为0x03
	0x0a, 0x30, //《
	0x08, 0x57, //圈
	0x08, 0x57, //圈
	0x59, 0x65, //教
	0x60, 0x4f, //你
	0xa9, 0x73, //玩
	0x55, 0x00, //U
	0x53, 0x00, //S
	0x42, 0x00, //B
	0x0b, 0x30, //》
	0x4b, 0x4e, //之
	0x55, 0x00, //U
	0x53, 0x00, //S
	0x42, 0x00, //B
	0x20, 0x9f, //鼠
	0x07, 0x68, //标
};
////////////////////////产品字符串结束////////////////////////////

////////////////////////序列号字符串开始////////////////////////////
//字符串“2008-08-22”的Unicode编码
//8位小端格式
code uint8_t SerialNumberStringDescriptor[22]={
	22,         //该描述符的长度为22字节
	0x03,       //字符串描述符的类型编码为0x03
	0x32, 0x00, //2
	0x30, 0x00, //0
	0x32, 0x00, //2
	0x35, 0x00, //5
	0x2d, 0x00, //-
	0x30, 0x00, //0
	0x38, 0x00, //8
	0x2d, 0x00, //-
	0x32, 0x00, //0
	0x34, 0x00  //7
};
////////////////////////序列号字符串结束////////////////////////////

/**************************************************************
function:Usb disconnect function
input: None
return: None
Note: None
**************************************************************/
void UsbDisconnect(void)
{
#ifdef DEBUG
	printf("Disconnect Usb link.\r\n");
#endif
	D12WriteCommand(D12_SET_MODE);
	D12WriteByte(0x06);  // set mode 1th byte, disconnetc USB resister
	D12WriteByte(0x47);  // set mode 2th byte, set div-clk, mode-0
	DelayXms(1000);
}

/**************************************************************
function:Usb connect function
input: None
return: None
Note: None
**************************************************************/
void UsbConnect(void)
{
#ifdef DEBUG
	printf("Connect Usb link.\r\n");
#endif
	D12WriteCommand(D12_SET_MODE);
	D12WriteByte(0x16);  // set mode 1th byte, connetc USB resister
	D12WriteByte(0x47);  // set mode 2th byte, set div-clk, mode-0
}

void UsbBusSuspend(void)
{
#ifdef DEBUG
	Prints("Usb bus suspend.\r\n");
#endif	
}

void UsbBusReset(void)
{
#ifdef DEBUG
	Prints("Usb bus reset.\r\n");
#endif	
	Ep1InIsBusy = 0;
}

void UsbEp0Out(void)
{
#ifdef DEBUG
	printf("Usb bus ep0 out.\r\n");
#endif	
	// read ep0 out end tramsfer state and clear irq flag
	// if bit5==1,package is setup package
	if(D12ReadEndPointLastStatus(0) & 0x20)
	{
		D12ReadEndPointBuffer(0, 16, Buffer);
		D12AcknowledgeSetup();
		D12ClearBuffer();

		bmRequestType = Buffer[0];
		bmRequest = Buffer[1];
		wValue = Buffer[2] + (((uint16_t)Buffer[3]) << 8);
		wIndex = Buffer[4] + (((uint16_t)Buffer[5]) << 8);
		wLength = Buffer[6] + (((uint16_t)Buffer[7]) << 8);
		if((bmRequestType & 0x80) == 0x80)
		{
			switch ((bmRequestType >> 5) & 0x03)
			{
			case 0:
				Prints("USB standart request: \r\n");
				switch (bmRequest)
				{
				case GET_CONFIGURATION:
					#ifdef DEBUG1
					Prints("get configuartion.");
					#endif
					break;
				case GET_DESCRIPTOR:
					// #ifdef DEBUG1
					Prints("  get description.\r\n");
					// #endif
					switch ((wValue >> 8) & 0xFF)
					{
					case DEVICE_DESCRIPTOR:
						printf("    get device descriptor.\r\n");
						pSendData = DeviceDescriptor;
						if(wLength > DeviceDescriptor[0])
						{
							SendLength = DeviceDescriptor[0];
							if(SendLength % DeviceDescriptor[7] ==0) {
								NeedZeroPacket = 1;
							}
						}
						else {
							SendLength = wLength;
						}
						UsbEp0SendData();
						break;
					case CONFIGURATION_DESCRIPTOR:
						Prints("    configuration descriptor\r\n");
						pSendData = ConfigurationDescriptor;
						SendLength = ConfigurationDescriptor[3];
						SendLength = SendLength * 256 + ConfigurationDescriptor[2];
						if(wLength > SendLength) {
							if(SendLength % DeviceDescriptor[7] == 0) {
								NeedZeroPacket = 1;
							}
						} else {
							SendLength = wLength;
						}
						UsbEp0SendData();
						break;
					
					case STRING_DESCRIPTOR:
						Prints("    string descriptor\r\n");
						switch (wValue & 0xFF)
						{
						case 0: // get labguage id
							printf("get language id\r\n");
							pSendData = LanguageId;
							SendLength = LanguageId[0];
							break;
						case 1: // manufactory ID
							printf("manufactory ID\r\n");
							pSendData = ManufacturerStringDescriptor;
							SendLength = ManufacturerStringDescriptor[0];
							break;
						case 2: // product ID
							printf("product id\r\n");
							pSendData = ProductStringDescriptor;
							SendLength = ProductStringDescriptor[0];
							break;
						case 3: // serial num
							printf("serial num\r\n");
							pSendData = SerialNumberStringDescriptor;
							SendLength = SerialNumberStringDescriptor[0];
							break;
						default:
							printf("Unknow index\r\n");
							SendLength = 0;
							NeedZeroPacket = 1;
							break;
						}
						if(wLength > SendLength)
						{
							if(SendLength % DeviceDescriptor[7] == 0)
							{
								NeedZeroPacket = 1;
							}
						}
						else
						{
							SendLength = wLength;
						}
						UsbEp0SendData();
						break;
					case REPORT_DESCRIPTOR:
						Prints("    report descriptor\r\n");
						pSendData = ReportDescriptor;
						SendLength = sizeof(ReportDescriptor);
						if(wLength > SendLength)
						{
							if(SendLength % DeviceDescriptor[7] == 0)
							{
								NeedZeroPacket = 1;
							}
						}
						else
						{
							SendLength = wLength;
						}
						UsbEp0SendData();
						break;
					default:
						Prints("   undefine descriptor\r\n");
						break;
					}
					break;
				case GET_INTERFACE:
					#ifdef DEBUG1
					Prints("get interface.");
					#endif
					break;

				case GET_STATUS:
					#ifdef DEBUG1
					Prints("get status")
					#endif
					break;

				case SYNCH_FRAME:
					#ifdef DEBUG1
					Prints("sync frame");
					#endif
					break;

				default:
					Prints("undefine request type");
					break;
				}
				break;
			case 1:
				Prints("USB class request");
				break;
			case 2:
				Prints("USB manufactory request");
				break;
			default:
				Prints("undefine request input");
				break;
			}
		}
		else
		{	// output request
			switch ((bmRequestType >> 5) & 0x03)
			{
			case 0:
				Prints("USB standard output Request: \r\n");
				switch (bmRequest)
				{
				case CLEAR_FEATURE:
					Prints("  OUT clear feature");
					break;

				case SET_ADDRESS:
					Prints("  OUT set addess\r\n");
					printf("  set adderss: 0x%x\r\n", wValue & 0xFF);
					D12SetAddress(wValue & 0xFF);
					SendLength = 0;
					NeedZeroPacket = 1;
					UsbEp0SendData();
					break;
				
				case SET_CONFIGURATION:
					Prints("  OUT set configuration\r\n");
					// 使能非0端点， 非0端点只有在设置为非0的配置后才使能
					D12SetEndpointEnable(wValue&0xFF);
					ConfigValue = wValue&0xFF;
					// 返回一个0长度的状态数据包
					SendLength = 0;
					NeedZeroPacket = 1;
					// 将数据通过EP0返回
					UsbEp0SendData();
					break;

				case SET_DESCRIPTOR:
					Prints("  OUT set descrption");
					break;

				case SET_FEATURE:
					Prints("  OUT set feature");
					break;

				case SET_INTERFACE:
					Prints("  OUT set interface");
				default:
					Prints("  undefine OUT request");
					break;
				}
				break;
			
			case 1:
				Prints("USB class OUT request");
				switch (bmRequest)
				{
				case SET_IDLE: {
					Prints("  set idle\r\n");
					SendLength = 0;
					NeedZeroPacket = 1;
					UsbEp0SendData();
				} break;
				
				default: {
					Prints("  unknow request\r\n");
				} break;
				}
				break;
			case 2:
				Prints("USB manufactory OUT request");
				break;
			default:
				Prints("undefine OUT request type");
				break;
			}
		}
	}
	else // normal data output
	{
		D12ReadEndPointBuffer(0, 16, Buffer);
		D12ClearBuffer();
	}
}

void UsbEp0In(void)
{
#ifdef DEBUG
	Prints("Usb bus Ep0 In.\r\n");
#endif	
	D12ReadEndPointLastStatus(1);
	UsbEp0SendData();
}

void UsbEp1Out(void)
{
#ifdef DEBUG
	Prints("Usb bus ep1 out.\r\n");
#endif	
}

void UsbEp1In(void)
{
#ifdef DEBUG
	Prints("Usb bus Ep1 In.\r\n");
#endif	
	// 读最后发送状态，清除端点1输入的中断标志位
	D12ReadEndPointLastStatus(3);
	// 端点1输入处于空闲状态
	Ep1InIsBusy = 0;
}

void UsbEp2Out(void)
{
#ifdef DEBUG
	Prints("Usb bus ep2 out.\r\n");
#endif
}

void UsbEp2In(void)
{
#ifdef DEBUG
	Prints("Usb bus Ep2 In.\r\n");
#endif	
}

/***
 * send pData with SendLength
*/
void UsbEp0SendData(void)
{
	if(SendLength > DeviceDescriptor[7]) {
		D12WriteEndPointBuffer(1, DeviceDescriptor[7], pSendData);
		SendLength -= DeviceDescriptor[7];
		pSendData += DeviceDescriptor[7];
	} else {
		if(SendLength != 0) {
			D12WriteEndPointBuffer(1, SendLength, pSendData);
			SendLength = 0;
		} else {
			if(NeedZeroPacket == 1) {
				D12WriteEndPointBuffer(1, 0, pSendData);
				NeedZeroPacket = 0;
			}
		}
	}
}







